package com.apache.nio.groupchat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class GroupChatServer {
  // 定义属性
  private Selector selector;
  private ServerSocketChannel listenChannel;
  private static final int PORT = 6667;

  // 构造器
  /** 初始化工作 */
  public GroupChatServer() {
    try {
      // 得到选择器
      selector = Selector.open();
      // ServerSocketChannel
      listenChannel = ServerSocketChannel.open();
      // 绑定端口
      listenChannel.socket().bind(new InetSocketAddress(PORT));
      // 设置非阻塞模式
      listenChannel.configureBlocking(false);
      // 将该listenChannel 注册到selector
      listenChannel.register(selector, SelectionKey.OP_ACCEPT);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  /** 监听 */
  public void listen() {
    System.out.println("监听线程: " + Thread.currentThread().getName());
    try {
      // 循环处理
      while (true) {
        int count = selector.select();
        if (count > 0) { // 有事件处理
          // 遍历得到selectionKey 集合
          Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
          while (iterator.hasNext()) {
            // 取出selectionkey
            SelectionKey key = iterator.next();
            // 监听到accept
            if (key.isAcceptable()) {
              SocketChannel socketChannel = listenChannel.accept();
              socketChannel.configureBlocking(false);
              // 将该 sc 注册到seletor
              socketChannel.register(selector, SelectionKey.OP_READ);
              // 提示
              System.out.println(socketChannel.getRemoteAddress() + " 上线 ");
            }
            if (key.isReadable()) { // 通道发送read事件，即通道是可读的状态
              // 处理读 (专门写方法..)
              readData(key);
            }
            // 当前的key 删除，防止重复处理
            iterator.remove();
          }
        } else {
          System.out.println("等待....");
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      // 发生异常处理....

    }
  }

  /** 读取客户端消息 */
  private void readData(SelectionKey key) {
    // 取到关联的channel
    SocketChannel channel = null;
    try {
      // 得到channel
      channel = (SocketChannel) key.channel();
      // 创建buffer
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      int count = channel.read(buffer);
      // 根据count的值做处理
      if (count > 0) {
        // 把缓存区的数据转成字符串
        String msg = new String(buffer.array());
        // 输出该消息
        System.out.println("form 客户端: " + msg);

        // 向其它的客户端转发消息(去掉自己), 专门写一个方法来处理
        sendInfoToOtherClients(msg, channel);
      }
    } catch (IOException e) {
      try {
        System.out.println(channel.getRemoteAddress() + " 离线了..");
        // 取消注册
        key.cancel();
        // 关闭通道
        channel.close();
      } catch (IOException e2) {
        e2.printStackTrace();
      }
    }
  }

  /**
   *  转发消息给其它客户(通道)
   */
  private void sendInfoToOtherClients(String msg, SocketChannel self) throws IOException {
    System.out.println("服务器转发消息中...");
    System.out.println("服务器转发数据给客户端线程: " + Thread.currentThread().getName());
    // 遍历 所有注册到selector 上的 SocketChannel,并排除 self
    for (SelectionKey key : selector.keys()) {
      // 通过 key  取出对应的 SocketChannel
      Channel targetChannel = key.channel();
      // 排除自己
      if (targetChannel instanceof SocketChannel && targetChannel != self) {
        // 转型
        SocketChannel dest = (SocketChannel) targetChannel;
        // 将msg 存储到buffer
        ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
        // 将buffer 的数据写入 通道
        dest.write(buffer);
      }
    }
  }

  public static void main(String[] args) {
    // 创建服务器对象
    GroupChatServer groupChatServer = new GroupChatServer();
    groupChatServer.listen();
  }
}

// 可以写一个Handler
class MyHandler {
  public void readData() {}

  public void sendInfoToOtherClients() {}
}
